
#include "rtde_hash.h"
#include "rtdeapi.h"


/******************** 哈希表构建 ********************/
// 构建输入变量哈希表
void build_input_hash(RtdeHandle rtdeHandle,int input_vars_num, const rtde_varlist_t input_vars[])
{
    RtdeDatespace_t *RtdeDatespace = get_rtde_dataspace(rtdeHandle);
    if(RtdeDatespace == NULL)
    {
        printf("build_input_hash---RtdeDatespace is NULL\n");
        return;
    }

    HASH_CLEAR(hh, RtdeDatespace->g_inputs_hash);
    RtdeDatespace->input_pool_idx = 0;
    int i;
    for(i = 0; i < input_vars_num; i++) {
        // 跳过无效条目
        if(strlen(input_vars[i].varname) == 0) continue;

        // 内存池检查
        if(RtdeDatespace->input_pool_idx >= MAX_INPUT_HASH) {
            printf("[ERROR] Input hash pool overflow!\n");
            break;
        }
        // 从内存池获取条目
        input_hash_t *entry = &(RtdeDatespace->input_hash_pool[RtdeDatespace->input_pool_idx++]);
        memset(entry, 0, sizeof(input_hash_t));
        strncpy(entry->key, input_vars[i].varname, RTDE_MAX_VARNAME);
        entry->index = i;
        // 添加哈希条目
        HASH_ADD_STR(RtdeDatespace->g_inputs_hash, key, entry);
    }
}

// 构建输出变量哈希表
void build_output_hash(RtdeHandle rtdeHandle,int output_vars_num, const rtde_varlist_t output_vars[]) 
{
    RtdeDatespace_t *RtdeDatespace = get_rtde_dataspace(rtdeHandle);
    if(RtdeDatespace == NULL)
    {
        printf("build_output_hash---RtdeDatespace is NULL\n");
        return;
    }

    HASH_CLEAR(hh, RtdeDatespace->g_outputs_hash);
    RtdeDatespace->output_pool_idx = 0;
    int i;
    for(i = 0; i < output_vars_num; i++) {
        if(strlen(output_vars[i].varname) == 0) continue;
        
        if(RtdeDatespace->output_pool_idx >= MAX_OUTPUT_HASH) {
            fprintf(stderr, "[ERROR] Output hash pool overflow!\n");
            break;
        }
        output_hash_t *entry = &(RtdeDatespace->output_hash_pool[RtdeDatespace->output_pool_idx++]);
        memset(entry, 0, sizeof(output_hash_t));
        strncpy(entry->key, output_vars[i].varname, RTDE_MAX_VARNAME);
        entry->index = i;
        HASH_ADD_STR(RtdeDatespace->g_outputs_hash, key, entry);
    }
}

// 构建方法哈希表
void build_method_hash(RtdeHandle rtdeHandle,int methods_num, const rtde_method_list_t methods_list[]) 
{
    RtdeDatespace_t *RtdeDatespace = get_rtde_dataspace(rtdeHandle);
    if(RtdeDatespace == NULL)
    {
        printf("build_method_hash---RtdeDatespace is NULL\n");  
    }
    
    HASH_CLEAR(hh, RtdeDatespace->g_methods_hash);
    RtdeDatespace->method_pool_idx = 0;
    int i;
    for(i = 0; i < methods_num; i++) {
        if(strlen(methods_list[i].methodname) == 0) continue;
        if(RtdeDatespace->method_pool_idx >= MAX_METHOD_HASH) {
            fprintf(stderr, "[ERROR] Method hash pool overflow!\n");
            break;
        }
        method_hash_t *entry = &(RtdeDatespace->method_hash_pool[RtdeDatespace->method_pool_idx++]);
        memset(entry, 0, sizeof(method_hash_t));
        strncpy(entry->key, methods_list[i].methodname, RTDE_MAX_METHOD_NAME);
        entry->index = i;
        HASH_ADD_STR(RtdeDatespace->g_methods_hash, key, entry);
    }
}

// 重置所有哈希表
void reset_all_hashes(RtdeHandle rtdeHandle) 
{
    RtdeDatespace_t *RtdeDatespace = get_rtde_dataspace(rtdeHandle);
    if(RtdeDatespace == NULL)
    {
        printf("reset_all_hashes---RtdeDatespace is NULL\n");  
    }

    HASH_CLEAR(hh, RtdeDatespace->g_inputs_hash);
    HASH_CLEAR(hh, RtdeDatespace->g_outputs_hash);
    HASH_CLEAR(hh, RtdeDatespace->g_methods_hash);
    RtdeDatespace->input_pool_idx = RtdeDatespace->output_pool_idx = RtdeDatespace->method_pool_idx = 0;
}


/******************** 查询接口 ********************/
int find_input_index(RtdeHandle rtdeHandle,const char *name) 
{
    RtdeDatespace_t *RtdeDatespace = get_rtde_dataspace(rtdeHandle);
    if(RtdeDatespace == NULL)
    {
        printf("find_input_index---RtdeDatespace is NULL\n");  
        return -1;
    }

    if(!name || !RtdeDatespace->g_inputs_hash) return -1;
    
    input_hash_t *entry = NULL;
    HASH_FIND_STR(RtdeDatespace->g_inputs_hash, name, entry);
    return entry ? entry->index : -1;
}

int find_output_index(RtdeHandle rtdeHandle,const char *name) 
{
    RtdeDatespace_t *RtdeDatespace = get_rtde_dataspace(rtdeHandle);
    if(RtdeDatespace == NULL)
    {
        printf("find_output_index---RtdeDatespace is NULL\n");  
        return -1;
    }

    if(!name || !RtdeDatespace->g_outputs_hash) return -1;
    
    output_hash_t *entry = NULL;
    HASH_FIND_STR(RtdeDatespace->g_outputs_hash, name, entry);
    return entry ? entry->index : -1;
}

int find_method_index(RtdeHandle rtdeHandle,const char *method) 
{
    RtdeDatespace_t *RtdeDatespace = get_rtde_dataspace(rtdeHandle);
    if(RtdeDatespace == NULL)
    {
        printf("find_method_index---RtdeDatespace is NULL\n");  
        return -1;
    }

    if(!method || !RtdeDatespace->g_methods_hash) return -1;
    
    method_hash_t *entry = NULL;
    HASH_FIND_STR(RtdeDatespace->g_methods_hash, method, entry);
    return entry ? entry->index : -1;
}


int multi_find(RtdeHandle rtdeHandle,const char *names, HashType type, int* resurlt) 
{
    // 创建一个可修改的副本，strtok会修改字符串
    char names_copy[RTDE_MAX_VARNAME*RTDE_MAX_OUTPUT_VAR];
    strncpy(names_copy, names, sizeof(names_copy) - 1);
    names_copy[sizeof(names_copy) - 1] = '\0'; // 确保字符串以null结尾

    // 计算逗号的数量
    int num_commas = 0;
    int i;
    for (i = 0; i < strlen(names_copy); i++) {
        if (names_copy[i] == ',') {
            num_commas++;
        }
    }
    // 根据逗号数量确定子字符串的数量
    int var_num = num_commas + 1;

    // 为子字符串数组分配内存
    char** vars_table = (char**)malloc(var_num * sizeof(char*));
    if (vars_table == NULL) {
        fprintf(stderr, "内存分配失败\n");
        exit(1);
    }

    // 使用strtok函数根据逗号拆分字符串
    char* token;
    int cnt = 0;
    token = strtok(names_copy, ",");
    while (token != NULL) {
        vars_table[cnt++] = token;
        token = strtok(NULL, ",");
    }

    for (i = 0; i < var_num; i++) 
    {
        switch (type) 
        {
            case INPUT: resurlt[i] = find_input_index(rtdeHandle,vars_table[i]); break;
            case OUTPUT: resurlt[i] = find_output_index(rtdeHandle,vars_table[i]); break;
            case METHOD: resurlt[i] = find_method_index(rtdeHandle,vars_table[i]); break;
        }
    }
    // 释放内存
    free(vars_table);
    return var_num;
}
